package com.jacksay.vikingfl.textinput
{
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.TextEvent;
	import flash.text.FontStyle;
	
	import mx.controls.TextInput;
	import mx.styles.CSSStyleDeclaration;
	
	/**
	 * Difusé lors d'un changement EFFECTIF du contenu texte.
	 */
	[Event(name="textChange", type="com.jacksay.vikingfl.textinput.PromptTextInputEvent")]
	
	
	/**
	 * TextInput 'amélioré', il prend en charge un message d'invite quand le 
	 * texte est vide. Il détecte également les changements réél du contenu.
	 */
	public class PromptTextInput extends TextInput
	{
		// ------------------------------------------------------------------
		//
		// PRIVATE PROPERTIES (Flags)
		//
		// ------------------------------------------------------------------
		
		/**
		 * 'flag' permettant de savoir si le prompt est appliqué ou pas.
		 * @private
		 */
		private var fPromptUse:Boolean = false;
		
		/**
		 * 'flag' utilisé pour évaluer les changements effectif du texte.
		 * @private
		 */
		private var fPrevText:String;
		
		
		
		// ------------------------------------------------------------------
		//
		// PUBLIC PROPERTIES
		//
		// ------------------------------------------------------------------
		
		// ------------------------------------------------------------------
		// prompt
		// ------------------------------------------------------------------
		/**
		 * Contenu du prompt affiché quand le champ de text est vide
		 *
		 * @default ""
		 * @since 2009-12-04
		 * @author jacksay14
		 */
		[Inspectable(category="Other", defaultValue=null, type="String")]
		public function get prompt() :String {
			return _prompt;
		}
		
		/**
		 * @private
		 */
		private var _prompt:String = "";
		
		/**
		 * @private
		 */
		public function set prompt( value:String ) :void {
			if( _prompt != value ){
				_prompt = value;
				applyPrompt();
			}
		}
		
		
		
		// ------------------------------------------------------------------
		//
		// PUBLIC PROPERTIES (Override & Accesseur)
		//
		// ------------------------------------------------------------------
		
		// ------------------------------------------------------------------
		// text
		// ------------------------------------------------------------------
		/**
		 * Retourne la valeur text réél
		 */
		[Bindable("textChange")]
		override public function get text():String {
			if( fPromptUse ){
				return "";
			} else {
				return super.text;
			}
		}
		
		/**
		 * @private
		 */
		override public function set text(value:String):void {
			if( value != text ){
				super.text = value;
				fPrevText = value;
				dispatchEvent(new PromptTextInputEvent(PromptTextInputEvent.TEXT_CHANGE));
				if( value == "" ){
					fPromptUse = true;
				} else {
					fPromptUse = false;
				}
				applyPrompt();
			}
		}
		
		
		
		// ------------------------------------------------------------------
		//
		// CONSTRUCTEUR
		//
		// ------------------------------------------------------------------
		public function PromptTextInput()
		{
			super();
		}
		
		
		
		
		// ------------------------------------------------------------------
		//
		// HANDLER (Override & Accesseur)
		//
		// ------------------------------------------------------------------
		
		/**
		 * Handler : Event.CHANGE
		 * Assure la détection des changements effectifs du text lors de la
		 * saisie utilisateur.
		 */
		protected function handlerTextInput( e:Event ):void{
			if( text != fPrevText ){
				fPrevText = text;
				dispatchEvent(new PromptTextInputEvent(PromptTextInputEvent.TEXT_CHANGE));
			}
		}
		
		
		/**
		 * Handler : FocusEvent.FOCUS_IN
		 * Supprime l'affichage du promp quand le champ prend le focus
		 */
		protected function handlerFocusIn( e:FocusEvent ) :void {
			if( fPromptUse ){
				fPromptUse = false;
				super.text = "";
				invalidateStyle();
			}
		}
		
		
		
		/**
		 * Handler : FocusEvent.FOCUS_OUT
		 * Applique le promp
		 * @see applyPrompt
		 */
		protected function handlerFocusOut( e:FocusEvent ) :void {
			applyPrompt();
		}
		
		
		
		/**
		 * Evalue le texte pour déterminer si le prompt doit être affiché ou pas
		 */
		protected function applyPrompt() :void {
			
			// Le prompt n'est pas en cours d'utilisation
			// et le contenu texte est vide
			if( !fPromptUse && super.text == "" )
			{
				fPromptUse = true;
				super.text = prompt;
			} 
			
			// Prompt en cours d'utilisation
			else if ( fPromptUse ) 
			{
				super.text = prompt;
			} 
			
			else {
				fPromptUse = false;
			}
			
			invalidateStyle();
		}
		
		
		// ---------------------------------------------------------------------
		//
		// STYLE
		//
		// ---------------------------------------------------------------------
		/**
		 * Evalue le style à appliqué en fonction de l'utilisation du prompt ou 
		 * pas.
		 */
		protected function invalidateStyle() :void {
			if( fPromptUse ){
				stylePrompt();
			} else {
				styleNormal();
			}
		}
		
		
		
		/**
		 * Applique le style quand le prompt est affiché
		 */
		protected function stylePrompt() :void {
			setStyle("fontWeight","normal");
			setStyle("fontStyle",FontStyle.ITALIC);
			setStyle("color", 0xAAAAAA);
		}
		
		
		
		/**
		 * Applique le style standard
		 */
		protected function styleNormal() :void {
			setStyle("fontWeight","normal");
			setStyle("fontStyle", FontStyle.REGULAR);
			setStyle("color", "none");
		}
		
		
		
		// ---------------------------------------------------------------------
		//
		// METHODES OVERRIDE
		//
		// ---------------------------------------------------------------------
		override protected function initializationComplete():void {
			super.initializationComplete();
			addEventListener(FocusEvent.FOCUS_IN, handlerFocusIn);
			addEventListener(FocusEvent.FOCUS_OUT, handlerFocusOut);
			addEventListener(Event.CHANGE, handlerTextInput);
		}
		
		override protected function commitProperties():void {
			super.commitProperties();
		}
		
		override protected function createChildren():void {
			super.createChildren();
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
			super.updateDisplayList(unscaledWidth, unscaledHeight);
		}
		
	}
}